package org.oy.sealogger.ui;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Vector;

import javax.swing.JCheckBoxMenuItem;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.KeyStroke;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.oy.sealogger.common.Messages;
import org.oy.sealogger.logger.XMLLogger;
import org.oy.sealogger.route.Route;

public class LoggerMenu {
	
	private static JPanel panel = null;
	
	/** Open route menuitems **/
	private JMenuItem openRoute = null;
	private JMenuItem routes = null;
	private JMenuItem showAllRoutes = null;
	private JMenuItem hideRoutes = null;
	private JMenuItem removeRoutes = null;
	
	private JFileChooser fc = null;
	private JColorChooser colorChooser = null;
	private LoggerGraphics lg = null;
	
	/** Logger menu **/
	//private JMenuBar MenuBar = null;
	private JMenu loggerMenu = null;
	private JMenuItem  loggerGraphics = null;
	private JMenuItem  selectAll = null;
	private JMenuItem  resetSelectAll = null;
	private JCheckBoxMenuItem  boatItem = null;
	private JCheckBoxMenuItem  compassItem = null;
	private JCheckBoxMenuItem  speedItem = null;
	private JCheckBoxMenuItem  depthItem = null;
	private JCheckBoxMenuItem  locationItem = null;
	private JCheckBoxMenuItem  infoItem = null;
	private JCheckBoxMenuItem  buttonItem = null;

	/**
	 * Constructs new LoggerMenu object
	 * @param panel
	 * @param menubar
	 * @param lg
	 */
	public LoggerMenu(JPanel panel, JMenuBar menubar, LoggerGraphics lg) {
		LoggerMenu.panel = panel;
		this.lg = lg;
		menubar.add(this.getLoggerMenu());
	}
	
	
	/**
	 * Retuns LoggerMenu. If LoggerMenu is not yet created then
	 * creates LoggerMenu. In this method every Logger menu item 
	 * is being added to Logger menu.
	 * @return LoggerMenu loggerMenu.
	 */
	private JMenu getLoggerMenu() {
		if (loggerMenu == null) {
			loggerMenu = new JMenu();
			loggerMenu.setText("Logger");
			loggerMenu.setEnabled(true);
			
			loggerMenu.add(getOpenRoute());
			loggerMenu.add(getRoutes());
			loggerMenu.add(new JSeparator());
			loggerMenu.add(getLoggerGraphics());

		}
		return loggerMenu;
	}
	
	/**
	 * Creates a menu item "Open route...".
	 * This menu item belongs to Logger menu.
	 * @return openRoute item.
	 */
	private JMenuItem getOpenRoute() {
		if (openRoute == null) {
			openRoute = new JMenuItem();
			openRoute.setText(Messages.getMessage("menu.label.open_route"));
			
			openRoute.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					
					File appDir = new File(System.getProperty("user.dir"));
					File logDir = new File(appDir, XMLLogger.LOGDIR);
					
					if (logDir.exists()) {
						fc = new JFileChooser(logDir);
					} else {
						fc = new JFileChooser(appDir);
					}
					
					int returnVal = fc.showOpenDialog(LoggerMenu.panel);
					
					if (returnVal == JFileChooser.APPROVE_OPTION) {
						File file = fc.getSelectedFile();
						boolean success = lg.openLogFile(file.getAbsolutePath());
						if (success) {
							if (colorChooser == null) {
								colorChooser = new JColorChooser(Color.BLACK);
								colorChooser.getSelectionModel().addChangeListener(new RouteColorChangeListener());
							}
							JDialog dialog = JColorChooser.createDialog(LoggerMenu.panel, Messages.getMessage("dialogue.title.route_colour"), false, colorChooser, null, null);
							dialog.setVisible(true);
						}
						
					} else {
						//LoggerGraphics.addMessageToList(new String("Opening cancelled by user."));
					}
					
					panel.repaint();
				}
			});
		}
		
		return openRoute;
	}
	
	private JMenuItem getRoutes() {
		if (routes == null) {
			routes = new JMenu(Messages.getMessage("menu.label.routes"));
			addRouteMenus();
		}
		
		return routes;
	}
	
	public void reloadRouteMenu() {
		routes.removeAll();
		addRouteMenus();
	}
	
	private JMenuItem addRouteMenus() {
		
		routes.add(getShowAllRoutes());
		routes.add(getHideRoutes());
		routes.add(getRemoveRoutes());
		routes.add(new JSeparator());
		
		routes.setEnabled(false);
		
		Vector<Route> routeVector = lg.getRoutes();
		if (routeVector != null) {
			for (Route r : routeVector) {
				JCheckBoxMenuItem routemenu = new JCheckBoxMenuItem(r.getName(), r.isVisible());
				routes.add(routemenu);
				routemenu.addActionListener(new RouteActionListener(r));
				routes.setEnabled(true);
			}
		}
		return routes;
	}
	
	/**
	 * Creates a menu item "Show all routes".
	 * This menu item belongs to Logger menu.
	 * @return selectRoutes item.
	 */
	private JMenuItem getShowAllRoutes() {
		if (showAllRoutes == null) {
			showAllRoutes = new JMenuItem();
			showAllRoutes.setText(Messages.getMessage("menu.label.show_all_routes"));		
			
			
			showAllRoutes.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					Vector<Route> routeVector = lg.getRoutes();
					if (routeVector != null && routeVector.size() != 0) {
						for (Route r : routeVector) {
							r.setVisible(true);
							reloadRouteMenu();
						}
					}
					panel.repaint();
				}
			});
		}
		
		Vector<Route> routeVector = lg.getRoutes();
		if (routeVector == null) {
			showAllRoutes.setEnabled(false);
		} else {
			showAllRoutes.setEnabled(false);
			for (Route r : routeVector) {
				if (!r.isVisible()) {
					showAllRoutes.setEnabled(true);
				}
			}
		}
		
		return showAllRoutes;
	}
	
	/**
	 * Creates a menu item "Reset all".
	 * This menu item belongs to Logger menu.
	 * @return reselectRoutes item.
	 */
	private JMenuItem getHideRoutes() {
		if (hideRoutes == null) {
			hideRoutes = new JMenuItem();
			hideRoutes.setText(Messages.getMessage("menu.label.hide_all_routes"));		
			
			hideRoutes.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					Vector<Route> routeVector = lg.getRoutes();
					if (routeVector != null && routeVector.size() != 0) {
						for (Route r : routeVector) {
							r.setVisible(false);
							reloadRouteMenu();
						}
					}
					panel.repaint();
				}
			});
		}
		
		Vector<Route> routeVector = lg.getRoutes();
		
		if (routeVector == null) {
			hideRoutes.setEnabled(false);
		} else {
			hideRoutes.setEnabled(false);
			for (Route r : routeVector) {
				if (r.isVisible()) {
					hideRoutes.setEnabled(true);
					continue;
				}
			}
			
		}
		
		return hideRoutes;
	}
	
	/**
	 * Creates a menu item "Remove routes".
	 * This menu item belongs to Logger menu.
	 * @return exitRoutes item.
	 */	
	private JMenuItem getRemoveRoutes() {
		if (removeRoutes == null) {
			removeRoutes = new JMenuItem();
			removeRoutes.setText(Messages.getMessage("menu.label.remove_all_routes"));		
			
			removeRoutes.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					Vector<Route> routeVector = lg.getRoutes();
					if (routeVector != null && routeVector.size() != 0) {
						routeVector.clear();
						routeVector = null;
						reloadRouteMenu();
					}
					panel.repaint();
				}
			});
		}
		
		Vector<Route> routeVector = lg.getRoutes();
		if (routeVector == null) {
			removeRoutes.setEnabled(false);
		} else {
			removeRoutes.setEnabled(true);
		}
		
		return removeRoutes;
	}
	
	private JMenuItem getLoggerGraphics() {
		if (loggerGraphics == null) {
			loggerGraphics = new JMenu();
			loggerGraphics.setText(Messages.getMessage("menu.label.graphics"));
			
			loggerGraphics.add(getShowAll());
			loggerGraphics.add(getResetSelectAll());			
			loggerGraphics.add(new JSeparator());
			loggerGraphics.add(getBoatItem());
			loggerGraphics.add(getCompassItem());
			loggerGraphics.add(getSpeedItem());
			loggerGraphics.add(getDepthItem());
			loggerGraphics.add(getLocationItem());
			loggerGraphics.add(getInfoItem());
			loggerGraphics.add(getButtonItem());

		}
		
		return loggerGraphics;
	}
	
	private JMenuItem getShowAll() {
		if (selectAll == null) {
			selectAll=new JMenuItem();
			selectAll.setText(Messages.getMessage("menu.label.show_all"));
			selectAll.setEnabled(true);
			selectAll.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0));
			
			
			selectAll.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					boatItem.setSelected(true);
					compassItem.setSelected(true);
					speedItem.setSelected(true);
					depthItem.setSelected(false); // Depth is set to false as default
					locationItem.setSelected(true);
					infoItem.setSelected(true);
					buttonItem.setSelected(true);
					resetSelectAll.setEnabled(true);
					selectAll.setEnabled(false);
					panel.repaint();
				}
			});
		}
		
		return selectAll;
	}
	
	private JMenuItem getResetSelectAll() {
		if (resetSelectAll == null) {
			resetSelectAll=new JMenuItem();
			resetSelectAll.setText(Messages.getMessage("menu.label.hide_all"));
			resetSelectAll.setEnabled(false);
			
			resetSelectAll.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0));
			
			resetSelectAll.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					boatItem.setSelected(false);
					compassItem.setSelected(false);
					speedItem.setSelected(false);
					depthItem.setSelected(false);
					locationItem.setSelected(false);
					infoItem.setSelected(false);
					buttonItem.setSelected(false);
					resetSelectAll.setEnabled(false);
					selectAll.setEnabled(true);
					panel.repaint();
				}
			});
		}
		
		return resetSelectAll;
	}
			
	/**
	 * Creates a menu item "Show boat".
	 * This menu item belongs to Logger menu.
	 * @return boatItem item.
	 */	
	private JCheckBoxMenuItem getBoatItem() {
		if (boatItem == null) {
			boatItem = new JCheckBoxMenuItem(Messages.getMessage("checkbox.label.show_boat"),false);
		}
		
		boatItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				panel.repaint();
			}
		});
		return boatItem;
	}
	
	/**
	 * Creates a menu item "Show compass".
	 * This menu item belongs to Logger menu.
	 * @return compassItem item.
	 */	
	private JCheckBoxMenuItem getCompassItem() {
		if (compassItem == null) {
			compassItem = new JCheckBoxMenuItem(Messages.getMessage("checkbox.label.show_compass"),false);
		}
		
		compassItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				panel.repaint();
			}
		});
		return compassItem;
	}	
	
	/**
	 * Creates a menu item "Show speed".
	 * This menu item belongs to Logger menu.
	 * @return speedItem item.
	 */	
	private JCheckBoxMenuItem getSpeedItem() {
		if (speedItem == null) {
			speedItem = new JCheckBoxMenuItem(Messages.getMessage("checkbox.label.show_speed"),false);
		}
		
		speedItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				panel.repaint();
			}
		});
		return speedItem;
	}
	
	/**
	 * Creates a menu item "Show depth".
	 * This menu item belongs to Logger menu.
	 * @return depthItem item.
	 */	
	private JCheckBoxMenuItem getDepthItem() {
		if (depthItem == null) {
			depthItem = new JCheckBoxMenuItem(Messages.getMessage("checkbox.label.show_depth"),false);
		}
		
		depthItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				panel.repaint();
			}
		});
		return depthItem;
	}
	
	
	/**
	 * Creates a menu item "Show location".
	 * This menu item belongs to Logger menu.
	 * @return locationItem item.
	 */	
	private JCheckBoxMenuItem getLocationItem() {
		if (locationItem == null) {
			locationItem = new JCheckBoxMenuItem(Messages.getMessage("checkbox.label.show_location"),false);
		}
		
		locationItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				panel.repaint();
			}
		});
		return locationItem;
	}
	
	/**
	 * Creates a menu item "Show buttons".
	 * This menu item belongs to Logger menu.
	 * @return buttonItem item.
	 */	
	private JCheckBoxMenuItem getButtonItem() {
		if (buttonItem == null) {
			buttonItem = new JCheckBoxMenuItem(Messages.getMessage("checkbox.label.show_buttons"),false);
		}
		
		buttonItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				panel.repaint();
			}
		});
		return buttonItem;
	}
	
	/**
	 * Creates a menu item "Show info".
	 * This menu item belongs to Logger menu.
	 * @return infoItem item.
	 */	
	private JCheckBoxMenuItem getInfoItem() {
		if (infoItem == null) {
			infoItem = new JCheckBoxMenuItem(Messages.getMessage("checkbox.label.show_info"),false);
		}
		
		infoItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				panel.repaint();
			}
		});
		return infoItem;
	}
	
	
	/**
	 * This returs has the user selected Show boat.
	 * LoggerGraphics class uses this method when draws graphics.
	 * @return boatItem
	 */
	public boolean isShowBoat() {
		return boatItem.isSelected();
	}
	
	/**
	 * This returs has the user selected Show compass.
	 * LoggerGraphics class uses this method when draws graphics.
	 * @return compassItem
	 */
	public boolean isShowCompass() {
		return compassItem.isSelected();
	}
	
	
	/**
	 * This returs has the user selected Show speed.
	 * LoggerGraphics class uses this method when draws graphics.
	 * @return speedItem
	 */
	public boolean isShowSpeed() {
		return speedItem.isSelected();
	}

	/**
	 * This returs has the user selected Show depth.
	 * LoggerGraphics class uses this method when draws graphics.
	 * @return depthItem
	 */
	public boolean isShowDepth() {
		return depthItem.isSelected();
	}
	
	/**
	 * This returs has the user selected Show location.
	 * LoggerGraphics class uses this method when draws graphics.
	 * @return locationItem
	 */
	public boolean isShowLocation() {
		return locationItem.isSelected();
	}
	
	/**
	 * This returs has the user selected Show buttons.
	 * LoggerGraphics class uses this method when draws graphics.
	 * @return buttonItem
	 */
	public boolean isShowButtons() {
		return buttonItem.isSelected();
	}
	
	
	/**
	 * This returs has the user selected Show buttons.
	 * LoggerGraphics class uses this method when draws graphics.
	 * @return buttonItem
	 */
	public boolean isShowInfo() {
		return infoItem.isSelected();
	}
	
	class RouteActionListener implements ActionListener {
		
		Route route;
		
		public RouteActionListener(Route r) {
			route = r;
		}
		
		public void actionPerformed(ActionEvent arg0) {
			route.toggleVisibility();
			reloadRouteMenu();
		}
		
	}
	
	class RouteColorChangeListener implements ChangeListener {

		public void stateChanged(ChangeEvent e) {
			Vector<Route> routes = lg.getRoutes();
			if (routes != null) {
				Color newColor = colorChooser.getColor();
				routes.lastElement().setColor(newColor);
			}
		}
		
	}
}
